home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / gfx / show / gs_src_gs.lha / gs5.03 / gdevstc2.c < prev    next >
C/C++ Source or Header  |  1996-05-09  |  14KB  |  428 lines

  1. /* Copyright (C) 1995, 1996 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gdevstc2.c */
  20. /* Epson Stylus-Color Printer-Driver */
  21.  
  22. /***
  23.      This file holds two implementations of the Floyd-Steinberg error
  24.      diffusion-algorithm. This algorithms are intended for high quality
  25.      printing in conjunction with the PostScript-Header stcolor.ps:
  26.  
  27.           gs -sDEVICE=stcolor <other options> stcolor.ps ...
  28.  
  29.      Most prominent option is -sDithering=xxx, to select the algorithm:
  30.  
  31.      fsmono - monochrome Floyd-Steinberg
  32.      fsrgb  - 3-Component Floyd-Steinberg
  33.      fsx4   - 4-Component Floyd-Steinberg (Bad results)
  34.  
  35.      fscmyk - Modified 4-Component Floyd-Steinberg
  36.               (Algorithmically identical with hscmyk, but slower)
  37.  
  38.  ***/
  39.  
  40. #include "gdevstc.h"
  41.  
  42. #include <stdlib.h>     /* for rand */
  43.  
  44. /*
  45.    Both algorithms require an error-buffer of 
  46.  
  47.        3 + 3*num_components +1*scan long-items.
  48.  
  49.    and must consequently set up to work with longs. 
  50.    It is just a Floyd-Steinberg-algorithm applied to each component.
  51.  
  52.  */
  53.  
  54. /*
  55.  * Due to the -selfdefined- ugly coding of the output-data, we need
  56.  * some conversion. But since this includes the black-separation, I
  57.  * did not change the definition.
  58.  *
  59.  * This algorithm stores the 1st component in the LSB, thus it
  60.  * reverts the order used by the basic driver.
  61.  */
  62.  
  63. static const byte grayvals[2]  = { 0, BLACK };
  64.  
  65. static const byte  rgbvals[8]  = {
  66.    0, RED, GREEN, RED|GREEN, BLUE, BLUE|RED, BLUE|GREEN, BLUE|RED|GREEN};
  67.  
  68. static const byte cmykvals[16] = {
  69.       0, CYAN,MAGENTA,CYAN|MAGENTA,YELLOW,YELLOW|CYAN,YELLOW|MAGENTA,BLACK,
  70.   BLACK,BLACK,  BLACK,       BLACK, BLACK,      BLACK,         BLACK,BLACK};
  71.  
  72. static const byte  *const pixelconversion[5] = {
  73.    NULL, grayvals, NULL, rgbvals, cmykvals};
  74.  
  75.  
  76. int 
  77. stc_fs(stcolor_device *sdev,int npixel,byte *bin,byte *bbuf,byte *out) 
  78. {
  79.  
  80.      long *in  = (long *) bin;
  81.      long *buf = (long *) bbuf;
  82.  
  83. /* ============================================================= */
  84.    if(npixel > 0) {  /* npixel >  0 -> scanline-processing       */
  85. /* ============================================================= */
  86.  
  87.       int bstep,pstart,pstop,pstep,p;
  88.       long spotsize,threshold,*errc,*errv;
  89.       const byte *pixel2stc;
  90.  
  91.       if(buf[0] >= 0) { /* run forward */
  92.         buf[0] = -1;
  93.         bstep  = 1;
  94.         pstep  = sdev->color_info.num_components;
  95.         pstart = 0;
  96.         pstop  = npixel * pstep;
  97.  
  98.       } else {                  /* run backward */
  99.         buf[0] =  1;
  100.         bstep  = -1;
  101.         pstep  = -sdev->color_info.num_components;
  102.         pstop  = pstep;
  103.         pstart = (1-npixel) * pstep;
  104.         out   += npixel-1;
  105.       }                   /* forward / backward */
  106.  
  107. /*    --------------------------------------------------------------------- */
  108.       if(in == NULL) return 0;  /* almost ignore the 'white calls' */
  109. /*    --------------------------------------------------------------------- */
  110.  
  111.       spotsize  = buf[1];
  112.       threshold = buf[2];
  113.       errc      = buf+3;
  114.       errv      = errc + 2*sdev->color_info.num_components;
  115.       pixel2stc = pixelconversion[sdev->color_info.num_components];
  116.  
  117.       for(p = pstart; p != pstop; p += pstep) { /* loop over pixels */
  118.          int c;     /* component-number */
  119.          int pixel; /* internal pxel-value */
  120.  
  121.          pixel = 0;
  122.  
  123.          for(c = 0; c < sdev->color_info.num_components; c++) { /* comp */
  124.             long cv; /* component value */
  125.  
  126.             cv = in[p+c] + errv[p+c] + errc[c] - ((errc[c]+4)>>3);
  127.             if(cv > threshold) {
  128.                pixel |= 1<<c;
  129.                cv    -= spotsize;
  130.             }
  131.             errv[p+c-pstep] += ((3*cv+8)>>4);        /* 3/16 */
  132.             errv[p+c      ]  = ((5*cv  )>>4)         /* 5/16 */
  133.                              + ((errc[c]+4)>>3);     /* 1/16 (rest) */
  134.             errc[c]          = cv                    /* 8/16 (neu) */
  135.                              - ((5*cv  )>>4)
  136.                              - ((3*cv+8)>>4);
  137.          }                                                      /* comp */
  138.  
  139.          *out = pixel2stc[pixel];
  140.          out += bstep;
  141.       }                                         /* loop over pixels */
  142.  
  143.  
  144. /* ============================================================= */
  145.    } else {          /* npixel <= 0 -> initialisation            */
  146. /* ============================================================= */
  147.  
  148.       int i,i2do;
  149.       long rand_max;
  150.       double offset,scale;
  151.  
  152. /*
  153.  * check wether the number of components is valid
  154.  */
  155.       if((sdev->color_info.num_components < 0)                         ||
  156.          (sdev->color_info.num_components >= countof(pixelconversion)) ||
  157.          (pixelconversion[sdev->color_info.num_components] == NULL)) return -1;
  158.  
  159. /*
  160.  * check wether stcdither & TYPE are correct
  161.  */
  162.       if(( sdev->stc.dither                    == NULL) ||
  163.          ((sdev->stc.dither->flags & STC_TYPE) != STC_LONG))         return -2;
  164.  
  165. /*
  166.  * check wether the buffer-size is sufficiently large
  167.  */
  168.       if(((sdev->stc.dither->flags/STC_SCAN) < 1) ||
  169.          ( sdev->stc.dither->bufadd          <
  170.           (3 + 3*sdev->color_info.num_components)))                  return -3;
  171. /*
  172.  * must neither have STC_DIRECT nor STC_WHITE
  173.  */
  174.       if(sdev->stc.dither->flags & (STC_DIRECT | STC_WHITE))         return -4;
  175.  
  176. /*
  177.  * compute initial values
  178.  */
  179. /* -- direction */
  180.      buf[0] = 1;
  181.  
  182. /* -- "spotsize" */
  183.      scale  = sdev->stc.dither->minmax[1];
  184.      buf[1] = scale + (scale > 0.0 ? 0.5 : -0.5);
  185.  
  186. /* -- "threshold" */
  187.      offset = sdev->stc.dither->minmax[0];
  188.      scale -= offset;
  189.      if((offset+0.5*scale) > 0.0) buf[2] = offset + 0.5*scale + 0.5;
  190.      else                         buf[2] = offset + 0.5*scale - 0.5;
  191.  
  192. /*
  193.  *   random values, that do not exceed half of normal value
  194.  */
  195.      i2do  = sdev->color_info.num_components * (3-npixel);
  196.      rand_max = 0;
  197.  
  198.      if(sdev->stc.flags & STCDFLAG0) {
  199.  
  200.         for(i = 0; i < i2do; ++i) buf[i+3] = 0;
  201.  
  202.      } else {
  203.  
  204.         for(i = 0; i < i2do; ++i) {
  205.            buf[i+3] = rand();
  206.            if(buf[i+3] > rand_max) rand_max = buf[i+3];
  207.         }
  208.  
  209.         scale = (double) buf[1] / (double) rand_max;
  210.  
  211.         for(i = 0; i < sdev->color_info.num_components; ++ i)
  212.            buf[i+3] = 0.25000*scale*(buf[i+3]-rand_max/2);
  213.  
  214.         for(     ; i < i2do; ++i) /* includes 2 additional pixels ! */
  215.            buf[i+3] = 0.28125*scale*(buf[i+3]-rand_max/2);
  216.  
  217.      }
  218.  
  219. /* ============================================================= */
  220.    } /* scanline-processing or initialisation */
  221. /* ============================================================= */
  222.  
  223.    return 0;
  224. }
  225.  
  226. /*
  227.  * Experimental CMYK-Algorithm
  228.  */
  229.  
  230. int 
  231. stc_fscmyk(stcolor_device *sdev,int npixel,byte *bin,byte *bbuf,byte *out) 
  232. {
  233.       long *in  = (long *) bin;
  234.       long *buf = (long *) bbuf;
  235.  
  236. /* ============================================================= */
  237.    if(npixel > 0) {  /* npixel >  0 -> scanline-processing       */
  238. /* ============================================================= */
  239.  
  240.       int bstep,pstart,pstop,pstep,p;
  241.       long spotsize,threshold,*errc,*errv;
  242.  
  243.       if(buf[0] >= 0) { /* run forward */
  244.         buf[0] = -1;
  245.         bstep  = 1;
  246.         pstep  = 4;
  247.         pstart = 0;
  248.         pstop  = npixel * pstep;
  249.  
  250.       } else {                  /* run backward */
  251.         buf[0] =  1;
  252.         bstep  = -1;
  253.         pstep  = -4;
  254.         pstop  = pstep;
  255.         pstart = (1-npixel) * pstep;
  256.         out   += npixel-1;
  257.       }                   /* forward / backward */
  258.  
  259.       spotsize  = buf[1];
  260.       threshold = buf[2];
  261.       errc      = buf+3;
  262.       errv      = errc + 2*4;
  263.  
  264.       for(p = 0; p < 4; ++p) errc[p] = 0;
  265.  
  266.       for(p = pstart; p != pstop; p += pstep) { /* loop over pixels */
  267.          int c;     /* component-number */
  268.          int pixel; /* internal pxel-value */
  269.          long cv,k;
  270.  
  271. /*
  272.  * Black is treated first, with conventional Floyd-Steinberg
  273.  */
  274.          k  = in[p+3];
  275.          cv = k + errv[p+3] + errc[3] - ((errc[3]+4)>>3);
  276.  
  277.          if(cv > threshold) {
  278.             pixel  = BLACK;
  279.             cv    -= spotsize;
  280.          } else {
  281.             pixel  = 0;
  282.          }
  283.  
  284.          errv[p+3-pstep] += ((3*cv+8)>>4);        /* 3/16 */
  285.          errv[p+3      ]  = ((5*cv  )>>4)         /* 5/16 */
  286.                           + ((errc[3]+4)>>3);     /* 1/16 (rest) */
  287.          errc[3]          = cv                    /* 8/16 (neu) */
  288.                           - ((5*cv  )>>4)
  289.                           - ((3*cv+8)>>4);
  290.  
  291. /*
  292.  * color-handling changes with black fired or not
  293.  */
  294.          if(pixel) {
  295.  
  296. /* -------- firing of black causes all colors to fire too */
  297.  
  298.             for(c = 0; c < 3; ++c) {
  299.                cv  = in[p+c] > k ? in[p+c] : k;
  300.                cv += errv[p+c] + errc[c] - ((errc[c]+4)>>3)-spotsize;
  301.                if(cv <= (threshold-spotsize)) cv = threshold-spotsize+1;
  302.  
  303.                errv[p+c-pstep] += ((3*cv+8)>>4);        /* 3/16 */
  304.                errv[p+c      ]  = ((5*cv  )>>4)         /* 5/16 */
  305.                                 + ((errc[c]+4)>>3);     /* 1/16 (rest) */
  306.                errc[c]          = cv                    /* 8/16 (neu) */
  307.                                 - ((5*cv  )>>4)
  308.                                 - ((3*cv+8)>>4);
  309.             }
  310.  
  311.          } else {
  312.  
  313. /* -------- if black did not fire, only colors w. larger values may fire */
  314.  
  315.             for(c = 0; c < 3; ++c) {
  316.  
  317.                cv  = in[p+c];
  318.  
  319.                if(cv > k) { /* May Fire */
  320.                   cv += errv[p+c] + errc[c] - ((errc[c]+4)>>3);
  321.                   if(cv > threshold) {
  322.                      cv -= spotsize;
  323.                      pixel |= CYAN>>c;
  324.                   }
  325.                } else {     /* Must not fire */
  326.                   cv = k + errv[p+c] + errc[c] - ((errc[c]+4)>>3);
  327.                   if(cv > threshold ) cv =  threshold;
  328.                }
  329.  
  330.                errv[p+c-pstep] += ((3*cv+8)>>4);        /* 3/16 */
  331.                errv[p+c      ]  = ((5*cv  )>>4)         /* 5/16 */
  332.                                 + ((errc[c]+4)>>3);     /* 1/16 (rest) */
  333.                errc[c]          = cv                    /* 8/16 (neu) */
  334.                                 - ((5*cv  )>>4)
  335.                                 - ((3*cv+8)>>4);
  336.             }
  337.          }
  338.  
  339.          *out = pixel;
  340.          out += bstep;
  341.       }                                         /* loop over pixels */
  342.  
  343.  
  344. /* ============================================================= */
  345.    } else {          /* npixel <= 0 -> initialisation            */
  346. /* ============================================================= */
  347.  
  348.       int i,i2do;
  349.       long rand_max;
  350.       double offset,scale;
  351.  
  352. /*
  353.  * check wether the number of components is valid
  354.  */
  355.       if(sdev->color_info.num_components != 4)                       return -1;
  356.  
  357. /*
  358.  * check wether stcdither & TYPE are correct
  359.  */
  360.       if(( sdev->stc.dither                    == NULL) ||
  361.          ((sdev->stc.dither->flags & STC_TYPE) != STC_LONG))         return -2;
  362.  
  363. /*
  364.  * check wether the buffer-size is sufficiently large
  365.  */
  366.       if(((sdev->stc.dither->flags/STC_SCAN) < 1) ||
  367.          ( sdev->stc.dither->bufadd          <
  368.           (3 + 3*sdev->color_info.num_components)))                  return -3;
  369. /*
  370.  * must neither have STC_DIRECT nor STC_WHITE
  371.  */
  372.       if(sdev->stc.dither->flags & (STC_DIRECT | STC_WHITE))         return -4;
  373.  
  374. /*
  375.  * compute initial values
  376.  */
  377. /* -- direction */
  378.      buf[0] = 1;
  379.  
  380. /* -- "spotsize" */
  381.      scale  = sdev->stc.dither->minmax[1];
  382.      buf[1] = scale + (scale > 0.0 ? 0.5 : -0.5);
  383.  
  384. /* -- "threshold" */
  385.      offset = sdev->stc.dither->minmax[0];
  386.      scale -= offset;
  387.      if(sdev->stc.flags & STCDFLAG1) {
  388.         buf[2] = (sdev->stc.extv[0][sdev->stc.sizv[0]-1] - sdev->stc.extv[0][0])
  389.                * scale / 2.0 + offset;
  390.      } else {
  391.         if((offset+0.5*scale) > 0.0) buf[2] = offset + 0.5*scale + 0.5;
  392.         else                         buf[2] = offset + 0.5*scale - 0.5;
  393.      }
  394.  
  395. /*
  396.  *   random values, that do not exceed half of normal value
  397.  */
  398.      i2do  = sdev->color_info.num_components * (3-npixel);
  399.      rand_max = 0;
  400.  
  401.      if(sdev->stc.flags & STCDFLAG0) {
  402.  
  403.         for(i = 0; i < i2do; ++i) buf[i+3] = 0;
  404.  
  405.      } else {
  406.  
  407.         for(i = 0; i < i2do; ++i) {
  408.            buf[i+3] = rand();
  409.            if(buf[i+3] > rand_max) rand_max = buf[i+3];
  410.         }
  411.  
  412.         scale = (double) buf[1] / (double) rand_max;
  413.  
  414.         for(i = 0; i < sdev->color_info.num_components; ++ i)
  415.            buf[i+3] = 0.25000*scale*(buf[i+3]-rand_max/2);
  416.  
  417.         for(     ; i < i2do; ++i) /* includes 2 additional pixels ! */
  418.            buf[i+3] = 0.28125*scale*(buf[i+3]-rand_max/2);
  419.  
  420.      }
  421.  
  422. /* ============================================================= */
  423.    } /* scanline-processing or initialisation */
  424. /* ============================================================= */
  425.  
  426.    return 0;
  427. }
  428.